package com.yunxin.core.domain.service.contact.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.core.domain.model.contact.*;
import com.yunxin.core.domain.service.contact.SendMessageService;
import com.yunxin.core.infra.common.contact.enums.TaskTypeEnum;
import com.yunxin.core.utils.infra.common.constant.CoreLockKey;
import com.yunxin.core.utils.infra.common.constant.CoreResultCode;
import com.yunxin.core.utils.infra.support.lock.DistributedLock;
import com.yunxin.core.utils.infra.support.lock.DistributedLockFactory;
import com.yunxin.core.utils.infra.utils.DateFormatUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author zero°
 * @since 2023-06-06
 */
@DS("core")
@Slf4j
@Component
@RequiredArgsConstructor
public class SendMessageFactory implements ApplicationContextAware {
    private static final Map<Integer, SendMessageService> SEND_MESSAGE_SERVICE_MAP = new HashMap<>();

    private final ContactMessageSendTaskDetailRepository messageSendTaskDetailRepository;

    private final ContactMessageTemplateRepository messageTemplateRepository;

    private final ContactMessageSendTaskExecuteRepository messageSendTaskExecuteRepository;

    private final DistributedLockFactory distributedLockFactory;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        //获取所有OrderIntoService类型的类
        Map<String, SendMessageService> map = applicationContext.getBeansOfType(SendMessageService.class);
        map.forEach((key, value) -> Optional.ofNullable(value.sourceType())
                .ifPresent(service -> SEND_MESSAGE_SERVICE_MAP.put(value.sourceType(), value)));
    }

    /**
     * 发送消息
     * @param variable 变量
     * @param taskCode 任务code
     * @param receiver 接收人
     */
    public void sendMessage(Object variable, String taskCode, List<String> receiver, String clientIp) {
        List<ContactMessageSendTaskDetail> list = messageSendTaskDetailRepository.listMessageSendTaskDetailByTaskCode(taskCode);
        list.forEach(x -> {
            Long taskExecuteId;
            if (TaskTypeEnum.PASSIVE.getTeakType().equals(x.getTaskType())) {
                String date = DateFormatUtils.X.getDateStrByNow();
                Date startTime = DateFormatUtils.X.getDateByStartTimeStr(date);
                Date endTime = DateFormatUtils.X.getDateByEndTimeStr(date);
                DistributedLock lock = distributedLockFactory.provideDistributedLock(CoreLockKey.CONTACT_TASK_EXECUTE.getPrefix() + x.getId());
                if (lock.tryLock(CoreLockKey.CONTACT_TASK_EXECUTE.getWaitTime(), CoreLockKey.CONTACT_TASK_EXECUTE.getReleaseTime(), CoreLockKey.CONTACT_TASK_EXECUTE.getTimeUnit())) {
                    try {
                        taskExecuteId = messageSendTaskExecuteRepository.getTaskExecuteIdByTaskDetailAndTime(x.getId(), startTime, endTime);
                        if (Objects.isNull(taskExecuteId)) {
                            ContactMessageSendTaskExecute messageSendTaskExecute = new ContactMessageSendTaskExecute();
                            messageSendTaskExecute.setTaskDetailId(x.getId());
                            messageSendTaskExecute.setTaskCode(taskCode);
                            messageSendTaskExecute.setTaskTotalCount(receiver.size());
                            messageSendTaskExecute.setExecuteTime(new Date());
                            messageSendTaskExecuteRepository.saveContactMessageSendTaskExecute(messageSendTaskExecute);
                            taskExecuteId = messageSendTaskExecute.getId();
                        } else {
                            messageSendTaskExecuteRepository.updateTotalCountById(taskExecuteId, receiver.size());
                        }
                    } finally {
                        lock.unlock();
                    }
                } else {
                    throw new BusinessException(CoreResultCode.SEND_MESSAGE_LOCK_ERROR);
                }
            } else {
                ContactMessageSendTaskExecute messageSendTaskExecute = new ContactMessageSendTaskExecute();
                messageSendTaskExecute.setTaskCode(taskCode);
                messageSendTaskExecute.setTaskTotalCount(receiver.size());
                messageSendTaskExecute.setExecuteTime(new Date());
                messageSendTaskExecuteRepository.saveContactMessageSendTaskExecute(messageSendTaskExecute);
                taskExecuteId = messageSendTaskExecute.getId();
            }
            SendMessageService sendMessageService = SEND_MESSAGE_SERVICE_MAP.get(x.getSendSource());
            if (Objects.isNull(sendMessageService)) {
                log.warn("发送渠道不存在, 任务详情id={}", x.getId());
                return;
            }
            String templateContent = messageTemplateRepository.getTemplateContentById(x.getMessageTemplateId());
            if (CharSequenceUtil.isEmpty(templateContent)) {
                log.warn("模板不不存在, 任务详情id={}, 模板id={}", x.getId(), x.getMessageTemplateId());
                return;
            }
            SendMessage<Object> sendMessage = new SendMessage<>();
            sendMessage.setMessageSubject(x.getMessageSubject());
            sendMessage.setMessageType(x.getMessageType());
            sendMessage.setTaskExecuteId(taskExecuteId);
            sendMessage.setTemplateContent(templateContent);
            sendMessage.setClientIp(clientIp);
            sendMessage.setReceiver(receiver);
            sendMessage.setVariable(variable);
            sendMessageService.sendMessage(sendMessage);
        });
    }

    /** 消息回调
     * @param source 渠道 10.短信 20.微信 30.app
     * @param messageCallbacks messageCallbacks
     */
    public void messageCallback(Integer source, List<MessageCallback> messageCallbacks) {
        SendMessageService sendMessageService = SEND_MESSAGE_SERVICE_MAP.get(source);
        if (Objects.isNull(sendMessageService)) {
            log.warn("回调渠道不存在");
            return;
        }
        messageCallbacks.forEach(sendMessageService::messageCallback);
    }



}
